#ifndef _FITCH_H
#define _FITCH_H

#include <string>
#include "matrix.h"
#include "tree.h"
#include "progress_indicator.h"




namespace fitch_tree
{

	//
	//	fitch_results
	//
	struct t_fitch_results
	{
		double sum_lengths;
		double avg_percent_stddev;
		unsigned cnt_trees_searched;
		unsigned best_iteration;
		std::string nh_tree;
		t_fitch_results():	sum_lengths(0.0), avg_percent_stddev(0.0),
				cnt_trees_searched(1),best_iteration(0){}
	};

	enum eJUMBLE	{eNO_JUMBLE, 	eDO_JUMBLE};
	enum eGLOBAL	{eNO_GLOBAL, 	eDO_GLOBAL};
	enum eMIN_EV	{eNO_MIN_EV, 	eDO_MIN_EV};
	enum eNEGLEN	{eNO_NEGLEN, 	eDO_NEGLEN};
	enum eKEEPLEN	{eNO_KEEPLEN,	eDO_KEEPLEN};





	//
	//	fitch_params
	//
	struct t_fitch_params
	{
		unsigned	outgrno;
		unsigned	njumble;
		bool		global;
		bool		jumble;
		bool		minev;
		bool		negallowed;
		double		power;
		t_fitch_params(	unsigned njumble_ = 20,
						eJUMBLE jumble_ = eDO_JUMBLE,
						eGLOBAL global_ = eDO_GLOBAL,
						eMIN_EV minev_ = eNO_MIN_EV,
						eNEGLEN negallowed_ = eNO_NEGLEN,
						double power_ = 2.0,
						unsigned outgrno_ = 1);
	};



	struct t_fitch_params_optimise : public t_fitch_params
	{
		t_fitch_params_optimise(    eKEEPLEN constrain_lengths = eDO_KEEPLEN,
									eGLOBAL global_ = eDO_GLOBAL,
									eMIN_EV minev_ = eNO_MIN_EV,
									eNEGLEN negallowed_ = eNO_NEGLEN,
									double power_ = 2.0,
									unsigned outgrno_ = 1) :
				t_fitch_params(20, eDO_JUMBLE, global_, minev_, negallowed_,
								power_, outgrno_),lengths(constrain_lengths == eDO_KEEPLEN){}
		bool lengths;
	};

	//
	//	fitch function
	//
	void fitch_make_nhstr(  const bcpp_matrix::t_matrix_f&		io,
							t_fitch_params&						params,
							t_fitch_results&					results);

	void fitch_make_tree(	bcpp_tree::t_tree& 				resulting_tree,
							const bcpp_matrix::t_matrix_f&		io,
							t_fitch_params&						params,
							t_fitch_results&					results);

	void optimize_nhstr(	const std::string&					tree_in_nh,
							const bcpp_matrix::t_matrix_f&		io,
                            t_fitch_params_optimise&			params,
							t_fitch_results&					results);
	void fitch_make_nhstr(  const bcpp_matrix::t_matrix_f&		io,
							t_fitch_params&						params,
							t_fitch_results&					results,
							t_progress_indicator&				dots);

	void fitch_make_tree(	bcpp_tree::t_tree& 				resulting_tree,
							const bcpp_matrix::t_matrix_f&		io,
							t_fitch_params&						params,
							t_fitch_results&					results,
							t_progress_indicator&				dots);

	void optimize_nhstr(	const std::string&					tree_in_nh,
							const bcpp_matrix::t_matrix_f&		io,
							t_fitch_params_optimise&			params,
							t_fitch_results&					results,
							t_progress_indicator&				dots);

}
#endif // _FITCH_H //
